package com.skyline.common.validation;

import java.io.Serializable;
import java.util.Date;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.validator.Field;
import org.apache.commons.validator.GenericTypeValidator;
import org.apache.commons.validator.GenericValidator;
import org.apache.commons.validator.ValidatorAction;
import org.apache.commons.validator.util.ValidatorUtils;

import com.skyline.common.util.WebHelper;

/**
 * 校验规则
 * */
public class FieldChecks implements Serializable {

	private static final long serialVersionUID = -4838856396216476764L;

	private static final Log LOGGER = LogFactory.getLog(FieldChecks.class);

	public static final String FIELD_TEST_NULL = "NULL";

	public static final String FIELD_TEST_NOTNULL = "NOTNULL";

	public static final String FIELD_TEST_EQUAL = "EQUAL";

	public static boolean validateRequired(Object bean, ValidatorAction va, Field field,
			Errors errors) {
		String value = extractValue(bean, field);
		if (GenericValidator.isBlankOrNull(value)) {
			rejectValue(errors, field, va);
			return false;
		} else {
			return true;
		}

	}

	public static boolean validateMask(Object bean, ValidatorAction va, Field field, Errors errors) {
		String mask = field.getVarValue("mask");
		String value = extractValue(bean, field);
		try {
			if (!GenericValidator.isBlankOrNull(value)
					&& !GenericValidator.matchRegexp(value, mask)) {
				rejectValue(errors, field, va);
				return false;
			} else {
				return true;
			}
		} catch (Exception e) {
			LOGGER.error(e.getMessage(), e);
		}
		return true;
	}

	public static Byte validateByte(Object bean, ValidatorAction va, Field field, Errors errors) {
		Byte result = null;
		String value = extractValue(bean, field);
		if (!GenericValidator.isBlankOrNull(value)) {
			result = GenericTypeValidator.formatByte(value);
			if (result == null) {
				rejectValue(errors, field, va);
			}
		}
		return result;
	}

	public static Short validateShort(Object bean, ValidatorAction va, Field field, Errors errors) {
		Short result = null;
		String value = extractValue(bean, field);
		if (!GenericValidator.isBlankOrNull(value)) {
			result = GenericTypeValidator.formatShort(value);
			if (result == null) {
				rejectValue(errors, field, va);
			}
		}
		return result;
	}

	public static Integer validateInteger(Object bean, ValidatorAction va, Field field,
			Errors errors) {
		Integer result = null;
		String value = extractValue(bean, field);
		if (!GenericValidator.isBlankOrNull(value)) {
			result = GenericTypeValidator.formatInt(value);
			if (result == null) {
				rejectValue(errors, field, va);
			}
		}
		return result;
	}

	public static Long validateLong(Object bean, ValidatorAction va, Field field, Errors errors) {
		Long result = null;
		String value = FieldChecks.extractValue(bean, field);
		if (!GenericValidator.isBlankOrNull(value)) {
			result = GenericTypeValidator.formatLong(value);
			if (result == null) {
				rejectValue(errors, field, va);
			}
		}
		return result;
	}

	public static Float validateFloat(Object bean, ValidatorAction va, Field field, Errors errors) {
		Float result = null;
		String value = extractValue(bean, field);
		if (!GenericValidator.isBlankOrNull(value)) {
			result = GenericTypeValidator.formatFloat(value);
			if (result == null) {
				rejectValue(errors, field, va);
			}
		}

		return result;
	}

	public static Double validateDouble(Object bean, ValidatorAction va, Field field, Errors errors) {
		Double result = null;
		String value = extractValue(bean, field);
		if (!GenericValidator.isBlankOrNull(value)) {
			result = GenericTypeValidator.formatDouble(value);
			if (result == null) {
				rejectValue(errors, field, va);
			}
		}

		return result;
	}

	public static Date validateDate(Object bean, ValidatorAction va, Field field, Errors errors) {
		Date result = null;
		String value = extractValue(bean, field);
		String datePattern = field.getVarValue("datePattern");
		String datePatternStrict = field.getVarValue("datePatternStrict");
		if (!GenericValidator.isBlankOrNull(value)) {
			try {
				if (datePattern != null && datePattern.length() > 0) {
					result = GenericTypeValidator.formatDate(value, datePattern, false);
				} else if (datePatternStrict != null && datePatternStrict.length() > 0) {
					result = GenericTypeValidator.formatDate(value, datePatternStrict, true);
				}
			} catch (Exception e) {
				LOGGER.error(e.getMessage(), e);
			}
			if (result == null) {
				rejectValue(errors, field, va);
			}
		}

		return result;
	}

	public static boolean validateIntRange(Object bean, ValidatorAction va, Field field,
			Errors errors) {
		String value = extractValue(bean, field);
		if (!GenericValidator.isBlankOrNull(value)) {
			try {
				int intValue = Integer.parseInt(value);
				int min = Integer.parseInt(field.getVarValue("min"));
				int max = Integer.parseInt(field.getVarValue("max"));
				if (!GenericValidator.isInRange(intValue, min, max)) {
					rejectValue(errors, field, va);
					return false;
				}
			} catch (Exception e) {
				rejectValue(errors, field, va);
				return false;
			}
		}
		return true;
	}

	public static boolean validateDoubleRange(Object bean, ValidatorAction va, Field field,
			Errors errors) {
		String value = extractValue(bean, field);
		if (!GenericValidator.isBlankOrNull(value)) {
			try {
				double doubleValue = Double.parseDouble(value);
				double min = Double.parseDouble(field.getVarValue("min"));
				double max = Double.parseDouble(field.getVarValue("max"));
				if (!GenericValidator.isInRange(doubleValue, min, max)) {
					rejectValue(errors, field, va);
					return false;
				}
			} catch (Exception e) {
				rejectValue(errors, field, va);
				return false;
			}
		}
		return true;
	}

	public static boolean validateFloatRange(Object bean, ValidatorAction va, Field field,
			Errors errors) {
		String value = extractValue(bean, field);
		if (!GenericValidator.isBlankOrNull(value)) {
			try {
				float floatValue = Float.parseFloat(value);
				float min = Float.parseFloat(field.getVarValue("min"));
				float max = Float.parseFloat(field.getVarValue("max"));
				if (!GenericValidator.isInRange(floatValue, min, max)) {
					rejectValue(errors, field, va);
					return false;
				}
			} catch (Exception e) {
				rejectValue(errors, field, va);
				return false;
			}
		}
		return true;
	}

	public static boolean validateEmail(Object bean, ValidatorAction va, Field field, Errors errors) {

		String value = extractValue(bean, field);

		if (!GenericValidator.isBlankOrNull(value) && !GenericValidator.isEmail(value)) {
			rejectValue(errors, field, va);
			return false;
		} else {
			return true;
		}
	}

	public static boolean validateMaxLength(Object bean, ValidatorAction va, Field field,
			Errors errors) {
		String value = extractValue(bean, field);
		if (value != null) {
			try {
				int max = Integer.parseInt(field.getVarValue("maxlength"));
				if (!GenericValidator.maxLength(value, max)) {
					rejectValue(errors, field, va);
					return false;
				}
			} catch (Exception e) {
				rejectValue(errors, field, va);
				return false;
			}
		}
		return true;
	}

	public static boolean validateMinLength(Object bean, ValidatorAction va, Field field,
			Errors errors) {
		String value = extractValue(bean, field);
		if (!GenericValidator.isBlankOrNull(value)) {
			try {
				int min = Integer.parseInt(field.getVarValue("minlength"));
				if (!GenericValidator.minLength(value, min)) {
					rejectValue(errors, field, va);
					return false;
				}
			} catch (Exception e) {
				rejectValue(errors, field, va);
				return false;
			}
		}
		return true;
	}

	public static boolean validateNotEqualTo(Object bean, ValidatorAction va, Field field,
			Errors errors) {
		String value = extractValue(bean, field);
		if (!GenericValidator.isBlankOrNull(value)) {
			try {
				String toId = field.getVarValue("toid");
				String toVal = ValidatorUtils.getValueAsString(bean, toId);
				if (value.equals(toVal)) {
					rejectValue(errors, field, va);
					return false;
				}
			} catch (Exception e) {
				rejectValue(errors, field, va);
				return false;
			}
		}
		return true;
	}

	public static boolean validateEqualTo(Object bean, ValidatorAction va, Field field,
			Errors errors) {
		String value = extractValue(bean, field);
		if (!GenericValidator.isBlankOrNull(value)) {
			try {
				String toId = field.getVarValue("toid");
				String toVal = ValidatorUtils.getValueAsString(bean, toId);
				if (!value.equals(toVal)) {
					rejectValue(errors, field, va);
					return false;
				}
			} catch (Exception e) {
				rejectValue(errors, field, va);
				return false;
			}
		}
		return true;
	}

	public static boolean validateGreatThan(Object bean, ValidatorAction va, Field field,
			Errors errors) {
		String value = extractValue(bean, field);
		if (!GenericValidator.isBlankOrNull(value)) {
			try {
				String toId = field.getVarValue("toid");
				String toVal = ValidatorUtils.getValueAsString(bean, toId);
				if (value.equals(toVal)) {
					rejectValue(errors, field, va);
					return false;
				}
			} catch (Exception e) {
				rejectValue(errors, field, va);
				return false;
			}
		}
		return true;
	}

	public static boolean validateSubmitToken(Object bean, ValidatorAction va, Field field,
			Errors errors) {
		String value = extractValue(bean, field);
		if (!WebHelper.isTokenValid(null, true, value)) {
			rejectValue(errors, field, va);
			return false;
		}
		return true;
	}
	
	public static boolean validateCertCode(Object bean, ValidatorAction va, Field field,
			Errors errors) {
		String value = extractValue(bean, field);
		if (!WebHelper.isCertCodeValid(null, value)) {
			rejectValue(errors, field, va);
			return false;
		}
		return true;
	}

	protected static String extractValue(Object bean, Field field) {
		String value = null;
		if (bean == null) {
			return null;
		} else if (bean instanceof String) {
			value = (String) bean;
		} else {
			value = ValidatorUtils.getValueAsString(bean, field.getProperty());
		}
		return value;
	}

	public static void rejectValue(Errors errors, Field field, ValidatorAction va) {
//		String fieldCode = field.getKey();
//		fieldCode = fieldCode.replace('(', '[').replace(')', ']');
		String message = ValidationUtils.getMessage(va, field);
		errors.addError(field.getProperty(), message);
	}

}
